package com.buaa.daas.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.buaa.daas.entity.StuDailyClockMessage;
import com.buaa.daas.entity.StuInfo;
import com.buaa.daas.mapper.StuDailyClockMessageMapper;
import com.buaa.daas.mapper.StuInfoMapper;
import com.buaa.daas.service.StuDailyClockMessageService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.buaa.daas.to.locationSend.*;
import com.buaa.daas.to.locationSimple.LocationSimpleObj;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author WangKangMing
 * @since 2021-06-04
 */
@Service
public class StuDailyClockMessageServiceImpl extends ServiceImpl<StuDailyClockMessageMapper, StuDailyClockMessage> implements StuDailyClockMessageService {

    @Autowired
    private StuDailyClockMessageMapper stuDailyClockMessageMapper;

    @Autowired
    private StuInfoMapper stuInfoMapper;

    @Override
    public List<StuDailyClockMessage> getStuDailyClockMessageList(String stuNum) {

        QueryWrapper<StuDailyClockMessage> stuDailyClockMessageQueryWrapper = new QueryWrapper<>();
        stuDailyClockMessageQueryWrapper.eq("stu_num", stuNum);

        List<StuDailyClockMessage> stuDailyClockMessageList = stuDailyClockMessageMapper.selectList(stuDailyClockMessageQueryWrapper);

        return stuDailyClockMessageList;
    }

    @Override
    public int saveStuDailyClockMessage(StuDailyClockMessage stuDailyClockMessage) {

        //插入一条新的记录
        int insert = stuDailyClockMessageMapper.insert(stuDailyClockMessage);

        return insert;
    }

    @Override
    public int deleteByIdAndStuNum(String autoid, StuInfo stuInfo) {

        QueryWrapper<StuDailyClockMessage> stuDailyClockMessageQueryWrapper = new QueryWrapper<>();
        stuDailyClockMessageQueryWrapper.eq("stu_num", stuInfo.getStuNum()).eq("auto_id", autoid);
        List<StuDailyClockMessage> stuDailyClockMessageList = stuDailyClockMessageMapper.selectList(stuDailyClockMessageQueryWrapper);
        if (stuDailyClockMessageList.size() == 1) {
            //如果能查到，说明删除的这个autoid是学生本人同时这个autoid也是存在的
            return stuDailyClockMessageMapper.delete(stuDailyClockMessageQueryWrapper);
        }

        return 0;
    }

    @Override
    public void autoDakaAll() {

        // 1.选出今日需要打卡的同学名单
        // 今天的时间要处理一下
        Date date = new Date();
        int year = date.getYear();
        int month = date.getMonth();
        int day = date.getDate();
        Date todayDate = new Date(year, month, day);
        List<StuDailyClockMessage> todayStuList = selectTodayStuList(todayDate);

        // 2.循环按照其预设进行打卡
        for (StuDailyClockMessage stuDailyClockMessage : todayStuList) {
            // 2.1 创建包含该对应cookie的http对象
            String stuNum = stuDailyClockMessage.getStuNum();
            QueryWrapper<StuInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("stu_num", stuNum);
            StuInfo stuInfo = stuInfoMapper.selectOne(wrapper);
            CloseableHttpClient client = addCookieHttpClient(stuInfo.getStuEaisess());

            try {
                //创建URLBuilder
                URIBuilder uriBuilder = new URIBuilder("https://app.buaa.edu.cn/buaaxsncov/wap/default/save");

                //2.创建HttpPost对象，设置URL地址
                URI uri = uriBuilder.build();
                HttpPost httpPost = new HttpPost(uri);

                httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36");

                //这个函数是用来添加打卡的参数的.加上请求体的参数之后的post请求
                // 2.2 预设打卡信息
                HttpPost newHttpPost = addParameter(httpPost, stuInfo, stuDailyClockMessage);

                //执行Post请求
                CloseableHttpResponse response = client.execute(newHttpPost);

                //7.获取结果实体
                HttpEntity entity = response.getEntity();
                String body = "";
                if (entity != null) {
                    //按指定编码转换结果实体为String类型
                    body = EntityUtils.toString(entity);
                    System.out.println(stuInfo.getStuName()+" post打卡请求的响应结果：" + body);

                    int successStr = body.indexOf("操作成功");
                    if (successStr != -1) {
                        // 打卡成功

                    } else {
                        // 打卡失败

                    }

                }
                //8.释放链接
                response.close();
                client.close();


            } catch (Exception e) {
                e.printStackTrace();
            }
        }


    }


    private List<StuDailyClockMessage> selectTodayStuList(Date todayDate) {

        QueryWrapper<StuDailyClockMessage> wrapper = new QueryWrapper<>();
        List<StuDailyClockMessage> allList = stuDailyClockMessageMapper.selectList(wrapper);
        List<StuDailyClockMessage> targetList = allList.stream().filter(o -> {
            return todayDate.compareTo(o.getStartTime()) >= 0 && todayDate.compareTo(o.getEndTime()) <= 0;
        }).collect(Collectors.toList());

        return targetList;
    }


    private CloseableHttpClient addCookieHttpClient(String eaiValue) {

        BasicCookieStore cookieStore = new BasicCookieStore();

        //设置eai-sess
        BasicClientCookie cookieEai = new BasicClientCookie("eai-sess", eaiValue);
        cookieEai.setVersion(0);
        cookieEai.setDomain("app.buaa.edu.cn");
        cookieEai.setPath("/");
        cookieStore.addCookie(cookieEai);

        //设置UUkey
        BasicClientCookie cookieUUkey = new BasicClientCookie("UUkey", "6d9f8a1dd6e0322c86e22b8ab6a8df3c");
        cookieUUkey.setVersion(0);
        cookieUUkey.setDomain("app.buaa.edu.cn");
        cookieUUkey.setPath("/");
        cookieStore.addCookie(cookieUUkey);

        //设置xxbh21.8
        BasicClientCookie cookieXxbh = new BasicClientCookie("xxbh21.8", "94424103");
        cookieXxbh.setVersion(0);
        cookieXxbh.setDomain("app.buaa.edu.cn");
        cookieXxbh.setPath("/");
        cookieStore.addCookie(cookieXxbh);

        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

        return httpClientBuilder.setDefaultCookieStore(cookieStore).build();
    }


    private HttpPost addParameter(HttpPost httpPost, StuInfo stuInfo, StuDailyClockMessage stuDailyClockMessage) {

        List<NameValuePair> parameters = new ArrayList<>();

        //这是默认的在北京校园里的，
        //sfzs=1
        parameters.add(new BasicNameValuePair("sfzs", stuDailyClockMessage.getAtSchoolOrNot().toString()));
        //&bzxyy=
        parameters.add(new BasicNameValuePair("bzxyy", stuDailyClockMessage.getNotAtSchoolType() == null ? "" : stuDailyClockMessage.getNotAtSchoolType().toString()));
        //&bzxyy_other=
        parameters.add(new BasicNameValuePair("bzxyy_other", stuDailyClockMessage.getNotAtSchoolOtherTypeDescription() == null ? "" : stuDailyClockMessage.getNotAtSchoolOtherTypeDescription()));

        // 以下字段是一样的，不会变
        //&brsfzc=1
        parameters.add(new BasicNameValuePair("brsfzc", "1"));
        //&tw=
        parameters.add(new BasicNameValuePair("tw", ""));
        //&sfcxzz=
        parameters.add(new BasicNameValuePair("sfcxzz", ""));
        //&zdjg=
        parameters.add(new BasicNameValuePair("zdjg", ""));
        //&zdjg_other=
        parameters.add(new BasicNameValuePair("zdjg_other", ""));
        //&sfgl=
        parameters.add(new BasicNameValuePair("sfgl", ""));
        //&gldd=
        parameters.add(new BasicNameValuePair("gldd", ""));
        //&gldd_other=
        parameters.add(new BasicNameValuePair("gldd_other", ""));
        //&glyy=
        parameters.add(new BasicNameValuePair("glyy", ""));
        //&glyy_other=
        parameters.add(new BasicNameValuePair("glyy_other", ""));
        //&gl_start=
        parameters.add(new BasicNameValuePair("gl_start", ""));
        //&gl_end=
        parameters.add(new BasicNameValuePair("gl_end", ""));
        //&sfmqjc=
        parameters.add(new BasicNameValuePair("sfmqjc", ""));
        //&sfzc_14=1
        parameters.add(new BasicNameValuePair("sfzc_14", "1"));
        //&sfqw_14=0
        parameters.add(new BasicNameValuePair("sfqw_14", "0"));
        //&sfqw_14_remark=
        parameters.add(new BasicNameValuePair("sfqw_14_remark", ""));
        //&sfzgfx=0
        parameters.add(new BasicNameValuePair("sfzgfx", "0"));
        //&sfzgfx_remark=
        parameters.add(new BasicNameValuePair("sfzgfx_remark", ""));
        //&sfjc_14=0
        parameters.add(new BasicNameValuePair("sfjc_14", "0"));
        //&sfjc_14_remark=
        parameters.add(new BasicNameValuePair("sfjc_14_remark", ""));
        //&sfjcqz_14=0
        parameters.add(new BasicNameValuePair("sfjcqz_14", "0"));
        //&sfjcqz_14_remark=
        parameters.add(new BasicNameValuePair("sfjcqz_14_remark", ""));
        //&sfgtjz_14=0
        parameters.add(new BasicNameValuePair("sfgtjz_14", "0"));
        //&sfgtjz_14_remark=
        parameters.add(new BasicNameValuePair("sfgtjz_14_remark", ""));
        //&szsqqz=0
        parameters.add(new BasicNameValuePair("szsqqz", "0"));
        //&sfyqk=
        parameters.add(new BasicNameValuePair("sfyqk", ""));
        //&szdd=1
        parameters.add(new BasicNameValuePair("szdd", "1"));


        String locationSend = stuDailyClockMessage.getLocationSend();
        LocationSendObj sendObj = null;
        if (locationSend == null) {
            //第一次的话，才需要转换和保存到数据库里
            sendObj = locationSimpleToSend(stuDailyClockMessage.getLocationSimple(), stuDailyClockMessage);
            locationSend = JSON.toJSONString(sendObj);
            stuDailyClockMessage.setLocationSend(locationSend);
            stuDailyClockMessageMapper.updateById(stuDailyClockMessage);
        } else {
            sendObj = JSON.parseObject(locationSend, LocationSendObj.class);
        }

        String province = sendObj.getAddressComponent().getProvince();
        String city = sendObj.getAddressComponent().getCity();
        city = city.replaceAll("[\\[\\]]", "");
        String district = sendObj.getAddressComponent().getDistrict();
        //这里要区分省份和直辖市，因为直辖市的city是“”，一个为空的字符串
        //province可以直接赋值
        parameters.add(new BasicNameValuePair("province", province));
        if ("".equals(city)) {
            //这是直辖市
            // 北京市
            parameters.add(new BasicNameValuePair("city", province));
            // "浙江省 杭州市 西湖区"  注意空格
            parameters.add(new BasicNameValuePair("area", province + " " + district));
        } else {
            //这是省份
            //杭州市
            parameters.add(new BasicNameValuePair("city", city));
            // "浙江省 杭州市 西湖区"  注意空格
            parameters.add(new BasicNameValuePair("area", province + " " + city + " " + district));
        }
        parameters.add(new BasicNameValuePair("address", sendObj.getFormattedAddress()));
        parameters.add(new BasicNameValuePair("geo_api_info", locationSend));

        //&gwdz=
        parameters.add(new BasicNameValuePair("gwdz", ""));

        Integer changeType = stuDailyClockMessage.getLocatChangeType();

        if (changeType == null) {
            //&is_move=0 位置没有变动
            parameters.add(new BasicNameValuePair("is_move", "0"));
            //&move_reason=
            parameters.add(new BasicNameValuePair("move_reason", ""));
            //&move_remark=
            parameters.add(new BasicNameValuePair("move_remark", ""));
        }else{
            // 位置变动后只有第1天才需要填变动
            Date date = new Date();
            int year = date.getYear();
            int month = date.getMonth();
            int day = date.getDate();
            Date todayDate = new Date(year, month, day);
            boolean firstDayFlag = (todayDate.compareTo(stuDailyClockMessage.getStartTime()) == 0);

            if(firstDayFlag){
                //&is_move=1 位置发生变动
                parameters.add(new BasicNameValuePair("is_move", "1"));
                //&move_reason=
                parameters.add(new BasicNameValuePair("move_reason", changeType.toString()));
                int changeTypeInt = changeType;
                if(changeTypeInt == 4){
                    parameters.add(new BasicNameValuePair("move_remark", stuDailyClockMessage.getLocatChangeOtherTypeDescription()));
                }else{
                    //&move_remark=
                    parameters.add(new BasicNameValuePair("move_remark", ""));
                }
            }else{
                //不是位置变动后的第1天，所以位置要改回成位置没有变动
                //&is_move=0 位置没有发生变动
                parameters.add(new BasicNameValuePair("is_move", "0"));
                //&move_reason=
                parameters.add(new BasicNameValuePair("move_reason", ""));
                //&move_remark=
                parameters.add(new BasicNameValuePair("move_remark", ""));
            }
        }



        parameters.add(new BasicNameValuePair("realname", stuInfo.getStuName()));


        //&number=ZY1906809
        //TODO 1.注意，这里是填学号
        parameters.add(new BasicNameValuePair("number", stuInfo.getStuNum()));
        //&uid=376649  TODO 这里的这个uid可能有坑
        parameters.add(new BasicNameValuePair("uid", "376649"));
        //&created=1620901044
        //TODO 2.注意，这里是前一天的时间戳
        parameters.add(new BasicNameValuePair("created", Long.toString(System.currentTimeMillis() - 86400 * 1000L)));
        //&date=20210513
        //TODO 3.注意，这里是前一天的日期
        String dateStr = new Date(System.currentTimeMillis() - 86400 * 1000L).toString().replace("-", "");
        parameters.add(new BasicNameValuePair("date", dateStr));
        //&id=2512472 TODO 这里的这个id可能有坑
        parameters.add(new BasicNameValuePair("id", "2512472"));
        //&gwszdd=
        parameters.add(new BasicNameValuePair("gwszdd", ""));
        //&created_uid=300068
        parameters.add(new BasicNameValuePair("created_uid", "300068"));

        UrlEncodedFormEntity formEntity = null;

        try {
            formEntity = new UrlEncodedFormEntity(parameters, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        httpPost.setEntity(formEntity);

        return httpPost;
    }

    private LocationSendObj locationSimpleToSend(String locationSimple, StuDailyClockMessage stuDailyClockMessage) {
        LocationSimpleObj simp = JSON.parseObject(locationSimple, LocationSimpleObj.class);


        LocationSendObj send = new LocationSendObj();
        send.setLocationType("ip");
        send.setAccuracy(null);
        send.setConverted(true);
        send.setMessage("Get ipLocation success.Get address success.");
        send.setStatus(1);
        send.setInfo("SUCCESS");
        send.setType("complete");
        send.setCEa("jsonp_779609_");
        Position position = new Position();
        position.setLat(Double.parseDouble(stuDailyClockMessage.getDailyClockLatitude().toString()));
        position.setLng(Double.parseDouble(stuDailyClockMessage.getDailyClockLongitude().toString()));
        position.setQ(position.getLng());
        position.setR(position.getLat());
        send.setPosition(position);
        //两个location之间的addressComponent不太一样，需要一一赋值过来
        AddressComponent sendAddrComp = new AddressComponent();
        com.buaa.daas.to.locationSimple.AddressComponent simAddrComp = simp.getRegeocode().getAddressComponent();
        sendAddrComp.setCitycode(simAddrComp.getCitycode());
        sendAddrComp.setAdcode(simAddrComp.getAdcode());
        sendAddrComp.setCountry("中国");
        sendAddrComp.setProvince(simAddrComp.getProvince());
        sendAddrComp.setCity(simAddrComp.getCity().toString());
        sendAddrComp.setDistrict(simAddrComp.getDistrict());
        sendAddrComp.setTownship(simAddrComp.getTownship());

        //addressComponent中的businessAreas也不太相同
        //这里的location和position完全一样
        Location location = new Location();
        location.setLat(position.getLat());
        location.setLng(position.getLng());
        location.setQ(position.getQ());
        location.setR(position.getR());

        List<BusinessAreas> businessAreasList = new ArrayList<>();
        List<com.buaa.daas.to.locationSimple.BusinessAreas> simpBuArList = simAddrComp.getBusinessAreas();
        for (com.buaa.daas.to.locationSimple.BusinessAreas areas : simpBuArList) {
            if (areas != null) {
                BusinessAreas businessAreas = new BusinessAreas();
                businessAreas.setName(areas.getName());
                businessAreas.setId(areas.getId());
                businessAreas.setLocation(location);
                businessAreasList.add(businessAreas);
            }
        }

        sendAddrComp.setBusinessAreas(businessAreasList);

        sendAddrComp.setNeighborhood(simAddrComp.getNeighborhood().getType());
        sendAddrComp.setNeighborhood(simAddrComp.getNeighborhood().getName());
        sendAddrComp.setBuilding(simAddrComp.getBuilding().getName());
        sendAddrComp.setBuildingType(simAddrComp.getBuilding().getType());
        sendAddrComp.setStreet(simAddrComp.getStreetNumber().getStreet());
        sendAddrComp.setStreetNumber(simAddrComp.getStreetNumber().getNumber());


        send.setAddressComponent(sendAddrComp);

        send.setFormattedAddress(simp.getRegeocode().getFormattedAddress());

        return send;
    }


}
